package com.sinodata.bsm.inmp.util;

import java.io.IOException;
import java.util.List;
import java.util.Vector;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.TableEvent;
import org.snmp4j.util.TableUtils;

/**
 * <p>
 * Description: 
 * </p>
 *
 * @author wangpeng
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2013-9-6 上午11:28:56          wangpeng        1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
public class SnmpUtil {

    /**
     * 
     * create a get PDU.
     * @param oids
     *    该pdu绑定的变量中的oid
     * @return
     */
    public static PDU createGetPdu(OID[] oids) {
        if (oids == null || oids.length < 1) {
            return null;
        }
        PDU pdu = new PDU();
        pdu.setType(PDU.GETNEXT);
        for (OID oid : oids) {
            pdu.add(new VariableBinding(oid));
        }
        return pdu;
    }

    /**
     * 
     * create a SNMPv2c/v3 getbulk PDU.
     * @param target
     * @param oid
     * @param maxRepetitions
     *    the maximum repetitions of repeatable variable bindings in GETBULK requests.an integer value >= 0.
     * @return
     *    a PDU instance 
     */
    public static PDU createGetBulkPdu(OID oid, int maxRepetitions) {
        PDU pdu = new PDU();
        pdu.setType(PDU.GETBULK);
        pdu.setMaxRepetitions(maxRepetitions);
        pdu.setNonRepeaters(0);
        pdu.add(new VariableBinding(oid));
        return pdu;
    }

    /**
     * 
     * 模拟snmpwalk获取数据
     * @param snmp
     *    a SNMP <code>Session</code> instance.
     * @param target
     *    a <code>Target</code> instance.
     * @param columnOIDs
     *    an array of OIDs of the columnar objects whose instances should be
     *    retrieved. The columnar objects may belong to different tables.
     *    Typically they belong to tables that share a common index or sub-index
     *    prefix. Note: The result of this method is not defined if instance OIDs
     *    are supplied in this array!
     * @param lowerBoundIndex
     *    an optional parameter that specifies the lower bound index
     *    If not null, all returned rows have an index greater than lowerBoundIndex.
     * @param upperBoundIndex
     *    an optional parameter that specifies the upper bound index.
     *    If not null, all returned rows have an index less or equal than upperBoundIndex.
     * @return
     */
    public static List<TableEvent> snmpWalk(Snmp snmp, CommunityTarget target, OID[] columnOIDs, OID lowerBoundIndex, OID upperBoundIndex) {
        TableUtils utils = new TableUtils(snmp, new DefaultPDUFactory(PDU.GETBULK));
        return utils.getTable(target, columnOIDs, lowerBoundIndex, upperBoundIndex);
    }

    /**
     * 
     * 同步获取pdu绑定的oid对应的数据值
     * @param snmp
     * @param pdu
     * @param target
     * @return
     * @throws IOException
     */
    public static Vector<? extends VariableBinding> sendRequest(Snmp snmp, PDU pdu, CommunityTarget target) throws IOException {
        ResponseEvent responseEvent = snmp.send(pdu, target);
        PDU response = responseEvent.getResponse();

        if (response == null) {
            return null;
        } else {
            if (response.getErrorStatus() == PDU.noError) {
                Vector<? extends VariableBinding> vbs = response.getVariableBindings();
                return vbs;
            } else {
                throw new IOException("获取数据失败>>> " + "Error:" + response.getErrorStatusText());
            }
        }
    }

    public static void main(String[] args) throws IOException {
        Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
        snmp.listen();

        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString("public"));
        target.setVersion(SnmpConstants.version2c);
        target.setAddress(new UdpAddress("10.1.0.177/161"));
        target.setTimeout(3000);
        target.setRetries(1);

                OID oids = new OID("1.3.6.1.4.1.15.0.2") ;
                PDU pud = createGetBulkPdu(oids, 678);
                Vector<? extends VariableBinding> vector = sendRequest(snmp, pud, target);
                for (VariableBinding vb : vector) {
                    System.out.println(vb);
                }

//        OID[] columnOIDs = new OID[] { new OID("1.3.6.1.4.1.15.0.3") };
//        OID lowerBoundIndex = new OID("484");
//        OID upperBoundIndex = new OID("1218");
//        List<TableEvent> tableList = snmpWalk(snmp, target, columnOIDs, lowerBoundIndex, upperBoundIndex);
//        for (TableEvent event : tableList) {
//            Integer value = null;
//            try {
//                value = event.getColumns()[0].getVariable().toInt();
//            } catch (Exception e) {
//                value = -1;
//            }
//            //System.out.println(value);
//            System.out.println(event.getIndex().toString() + "," + event.getColumns()[0].getVariable().toString());
//        }
    }
}
